package io.elegant
import android.content.Context
import io.elegant.sessions.ActivitySession
import io.grpc.Metadata
import io.grpc.CallCredentials
import io.grpc.ManagedChannel
import io.grpc.ManagedChannelBuilder
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit

object entry {
    private lateinit var managedChannel: ManagedChannel
    /**
     * 连接服务器
     * */
    fun connect() = managedChannel.resetConnectBackoff()
    /**
     * 初始化
     * @param host 服务器地址
     * */
    fun initialize(host: String) {
        managedChannel = ManagedChannelBuilder
            .forAddress(host, 8000)
            .keepAliveTime(60, TimeUnit.SECONDS)
            .keepAliveTimeout(30, TimeUnit.SECONDS)
            .keepAliveWithoutCalls(true)
            .enableRetry()
            .usePlaintext()
            .build()
    }
    /**
     * 逆初始化
     * */
    fun uninitialize() = managedChannel.shutdown().awaitTermination(1, TimeUnit.SECONDS)
    fun getActivitySession(context: Context, clientId: String) = getApiStub(clientId).let {
        ActivitySession(it, context)
    }
    /**
     * 获取GRPC连接对象
     * */
    private fun getApiStub(clientId: String): ElegantApiGrpc.ElegantApiStub = ElegantApiGrpc
        .newStub(managedChannel)
        .withCallCredentials(object: CallCredentials() {
            override fun applyRequestMetadata(
                requestInfo: RequestInfo?,
                appExecutor: Executor?,
                applier: MetadataApplier?
            ) {
                applier
                    ?.apply(Metadata().apply {
                        put(Metadata.Key.of("client-id", Metadata.ASCII_STRING_MARSHALLER), clientId)
                        put(Metadata.Key.of("platform", Metadata.ASCII_STRING_MARSHALLER), "Android")
                    })
            }
        })
    private val INT_MARSHALLER = object: Metadata.AsciiMarshaller<Int> {
        override fun parseAsciiString(serialized: String?) = serialized?.toInt() ?: 0
        override fun toAsciiString(value: Int?) = value?.toString()
    }
}